<?php
/**
 * Modelo de Listagem de tabelas relacionadas
 * Recuperar os dados de uma entidade com dados espalhados em várias tabelas relacionadas
 * 
 * @example PC4_Crud_NoticiasComCategorias (UmParaMuitos) e PC4_Crud_NoticiasComTags (MuitosParaMuitos)
 * @author Emanuel Melo e Renato Lenz @ PC4 Team
 */
class PC4_Crud_Tabelas extends PC4_Db_Table {
	
	// TODO: adicionar métodos para manipular as configurações de junções de tabelas
	/**
	 * Construtor pode receber dois novos índices no $config:
	 * @param array $config['tabelas']
	 * 		array(
	 * 			tabela => array(
	 * 				['campos' => array([alias => ]nome_campo),]
	 * 				['join' => 'inner',]
	 * 				['pk' => tabelaRelacionada.campo,
	 * 				'fk' => tabelaPrincipal.campo, |
	 * 				'on' => string]
	 * 			)
	 * 		)
	 * @param String $config['group']
	 */
	public function __construct($config = null, $definition = null) {
		parent::__construct($config, $definition);
		$this->addTabelas($config['tabelas']);
		if ($config['decorado'] != null) {
			$this->addTabelas($config['decorado']->config['tabelas']);
		}

		/*
new d($this->config['decorado']->config, get_class($this));
new d($this->config['decorado']->config['tabelas'], get_class($this));
new d($config['tabelas'], get_class($this));
new d($this->config['tabelas'], get_class($this));*/
	}
	public function preparaConsulta($where = null, $order = null, $count = null, $offset = null) {
		$where = parent::preparaConsulta($where, $order, $count, $offset);
		$where->setIntegrityCheck(false);
		$aliasPrincipal = $this->alias;

		foreach ($this->config['tabelas'] as $tabela => $infos) {
			// O espaço que separa o nome da tabela do alias
			if (strrpos($tabela, ' ') === false) {
				$aliasTabela = $this->getAlias($tabela);
			}
			else {
				list($tabela, $aliasTabela) = explode(' ', $tabela);
			}
			// define a condição de JOIN
			if (empty($infos['on'])) {
				if (empty($infos['pk'])) {
					$infos['pk'] = $aliasTabela . '.id';
				}
				if (empty($infos['fk'])) {
					$infos['fk'] = $aliasPrincipal . '.id_' . $tabela;
				}
				$infos['on'] = $infos['pk'] . ' = ' . $infos['fk'];
			}
			// define o tipo de JOIN
			if (empty($infos['join'])) {
				$infos['join'] = 'inner';
			}
			$join = 'join' . ucfirst($infos['join']);
			// define os campos
			foreach ((array)$infos['campos'] as $alias => $campo) {
				if (is_numeric($alias)) {
					$alias = end(explode('.', $campo)) . ucfirst($tabela);
				}
				if (strpos($campo, '.') === false) {
					$campo = $aliasTabela . '.' . $campo;
				}
				$where->columns(array($alias => $campo));
			}
			// realiza o JOIN
	    	$where->$join(array($aliasTabela => $tabela), $infos['on'], array());
		}
		// realiza o agrupamento, se houver
		if (!empty($this->config['group'])) {
			$where->group($this->config['group']);
		}
    	return $where;
	}
	
	public function addTabela($tabela, $opcoes) {
		if ($this->config['tabelas'] == null) {
			$this->config['tabelas'] = array();
		}
		$this->config['tabelas'][$tabela] = $opcoes;
	}
	public function addTabelas($tabelas) {
		foreach ((array)$tabelas as $tabela => $opcoes) {
			if (!empty($tabela)) {
				$this->addTabela($tabela, $opcoes);
			}
		}
	}
	public function addGroup($group) {
		$this->config['group'][$group] = $group;
	}

}
?>